# coding=utf-8
import base64
import traceback
from Common.FontColor import outcome
from Common.DataHandle import Matching
from Common.DataHandle import CaseHandle
import unittest
from unittest import TestCase
from Common.ReadYaml import ConfigYaml, CaseYaml
from Common.ReadWriteIni import ReadWrite
from Common.Results import results
from Common.MyRedis import ReDis
from Common.DataHandle import SqlHandle, Assertion
import os
from Common.Route import Any_Path
from Common.MySql import Sql


class MyTest(TestCase):

    def __init__(self, methodName='runTest', param=None):
        TestCase.__init__(self, methodName)
        self.param = param
        self.result = None
        self.time = 0
        self.abnormal = ''
        self.singular = ''

    @classmethod
    def setUpClass(self):
        """

        :return:
        """
        self.token_key = ConfigYaml('token_key').base_config
        self.token_value = ReadWrite().read_ini_token()
        self.headers = {self.token_key: self.token_value}


    @classmethod
    def tearDownClass(self):
        pass

    def setUp(self):
        """

        :return:
        """
        from Common.Login import Login
        self.module = self.__module__
        self.className = self.__class__.__name__
        self.case_name = self._testMethodName
        self.projectName = ConfigYaml("projectName").base_config
        self.headers.update({Login.content_type_key: Login.content_json_type_value})
        self.all_case_data = {}

        case_file_list = [file for file in os.listdir(Any_Path(self.projectName)) if file != "Data.yaml" and '.yaml' in file]

        for case_file in case_file_list:
            self.all_case_data.update(CaseYaml(file=case_file).all_case)

        if self.all_case_data:
            self.cls_data, self.fun_data = CaseHandle(self.className, self.case_name, self.all_case_data)

        self.sql = ConfigYaml('sql').base_config
        self.redis = ConfigYaml('redis').base_config
        if self.fun_data.get('url'):
            self.url = self.fun_data.get('url')
        else:
            self.url = self.cls_data.get('url')
        if self.fun_data.get('author'):
            self.author = self.fun_data.get('author')
        else:
            self.author = "None"
        if self.fun_data.get('case_name'):
            self.notes = self.fun_data.get('case_name')
        else:
            self.notes = "None"
        if self.fun_data.get('bar'):
            self.data = self.fun_data.get('bar')
        else:
            self.data = {}
        if self.fun_data.get('level'):
            self.level = self.fun_data.get('level')
        else:
            self.level = "中"

        self.switch = self.fun_data.get('switch')
        self.database_name = self.fun_data.get('database_name')
        self.sql_command = self.fun_data.get('sql_sentence')
        self.listing = self.fun_data.get('listing')
        self.method = self.fun_data.get('mode')
        self.expected = self.fun_data.get('expected')
        self.table_name = self.fun_data.get('table_name')

    def tearDown(self):
        """

        :return:
        """
        if self.sql_command:
            sql_command = self.sql_command.format(self.table_name, self.listing, self.expected_value)
        else:
            sql_command = ''

        try:
            self.actual = Matching("success", self.result)
        except Exception:
            self.actual = 'None'
        try:
            Assertion(self.result, self.assertEqual, actualone="success",
                      expectone=self.expected[0],
                      ).datahandle()
            if self.switch:
                try:
                    self.sql_value = Sql(sqlname=self.database_name, sql=sql_command).execute_sql()
                    if self.sql_value:
                        self.sql_value = self.sql_value[0].get(self.listing)
                    else:
                        self.sql_value = None
                    self.assertEqual(self.expected_value, self.sql_value, msg="接口存储值与数据库查询值不一致...")

                except:
                    pass
        except:
            self.abnormal = str(traceback.format_exc()) + f"用例层级：{self.module}>>>{self.className}>>>{self.case_name}"
            outcome('red', self.abnormal)

        resonse = results(
            expected=self.expected[0],
            actual=self.actual,
            usetime=self.time,
            singular=self.singular,
            result=self.result,
            param=self.data
            )
        Resonse = str(base64.b64encode(str(resonse).encode('utf-8')), 'utf-8')
        if self.sql:
            mysql = SqlHandle(self.case_name,self.notes,self.level, self.url, self.abnormal, self.author, self.time, Resonse, self.className)
            mysql.implement()
            mysql.insert_result_table()

        else:
            data = SqlHandle(self.case_name,self.notes,self.level,self.url,self.abnormal,self.author,self.time,Resonse,self.className).data_handle()
            ReDis(data).lpush()


    @staticmethod
    def parametrize(class_name, param=None):
        '''
        :param testcase_klass:
        :param param:
        :return:
        '''
        """ Create a suite containing all tests taken from the given
            subclass, passing them the parameter 'param'.
        """
        testloader = unittest.TestLoader()
        testnames = testloader.getTestCaseNames(class_name)
        suite = unittest.TestSuite()
        for name in testnames:
            suite.addTest(class_name(name, param=param))
        return suite

